import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_lui/flutter_lui.dart';
import 'package:flutter_lui/src/l_style.dart';

enum LPopoverPosition {
  top,
  bottom,
}

class LPopover extends StatelessWidget {
  /// 要悬浮菜单的组件
  final Widget child;

  /// 菜单内容
  final String label;

  /// 菜单显示位置
  /// 默认为上
  final LPopoverPosition position;

  /// 菜单宽度
  /// 默认为屏幕宽度的3/4
  final double? popWidth;
  final GlobalKey _globalKey = GlobalKey();
  LPopover(
      {Key? key,
      required this.label,
      required this.child,
      this.popWidth,
      this.position = LPopoverPosition.top})
      : super(key: key);

  static OverlayEntry? _ove;

  _hide() {
    if (_ove != null) {
      _ove!.remove();
      _ove = null;
    }
  }

  _show(context) {
    FocusScope.of(context).unfocus();
    _hide();
    OverlayState os = Overlay.of(context);
    _ove = handleShowPopup();
    os.insert(_ove!);
  }

  handleShowPopup() {
    _hide();
    RenderBox renderBox =
        _globalKey.currentContext!.findRenderObject() as RenderBox;
    var childSize = renderBox.size;
    var childPosition = renderBox.localToGlobal(Offset.zero);
    double shapWidth = lrpx(20);
    double shapHiehgt = lrpx(10);

    /// 整体上下偏移量
    double offset = lrpx(3);
    double menuWidth = popWidth ?? PageSize.width / 4 * 3;
    double screenPadding = lrpx(10);

    /// 三角形左边距，一般应该在被点击的组件最中间，最少应该大于marginHorizontal + 10 加10是圆角问题，显示到最边边不好看
    double shapeLeft = max(
        childPosition.dx + (childSize.width - shapWidth) / 2, screenPadding);

    /// 三角形也不能超过右侧自身的宽度 + 10 + margin
    shapeLeft = min(shapeLeft, PageSize.width - screenPadding - shapWidth);

    /// 三角型底部到屏幕底部的距离,用于显示在上方 避免了计算菜单的高度
    double shapBottom = PageSize.height - (childPosition.dy - offset);

    /// 三角型顶部到屏幕顶部的距离,用于显示在下方  避免了计算菜单的高度
    double shapTop = childPosition.dy + childSize.height + offset;

    /// 计算菜单显示位置 同三角形
    double menuLeft =
        max(10, (childPosition.dx + childSize.width / 2) - menuWidth / 2);
    menuLeft = min(menuLeft, PageSize.width - screenPadding - menuWidth);

    /// 菜单底部距离屏幕顶部的高度
    var menuBottom = shapBottom + shapHiehgt - 1;

    /// 菜单顶部距离屏幕顶部的高度
    var menuTop = shapTop + shapHiehgt - 1;

    return OverlayEntry(builder: (context) {
      return GestureDetector(
        onTap: _hide,
        child: Scaffold(
          backgroundColor: Colors.transparent,
          body: Container(
            color: Colors.transparent,
            child: Stack(
              children: <Widget>[
                Positioned(
                  left: menuLeft,
                  bottom: position == LPopoverPosition.top ? menuBottom : null,
                  top: position == LPopoverPosition.bottom ? menuTop : null,
                  child: LBox(
                      backgroundColor: Colors.white,
                      boxShadow: [
                        BoxShadow(
                            color: Colors.black.withOpacity(0.2),
                            offset: Offset(0, lrpx(0)),
                            blurRadius: lrpx(32),
                            spreadRadius: lrpx(0)),
                      ],
                      borderRadius: [LStyle.borderRadius],
                      border: const [true],
                      borderSide: BorderSide(color: LUI.instance.borderColor),
                      padding: [lrpx(10)],
                      width: menuWidth,
                      child: LText(label)),
                ),
                Positioned(
                    bottom:
                        position == LPopoverPosition.top ? shapBottom : null,
                    top: position == LPopoverPosition.bottom ? shapTop : null,
                    left: shapeLeft,
                    child: CustomPaint(
                      painter: _BorderPainter(
                          lineColor: LUI.instance.borderColor,
                          position: position),
                      child: ClipPath(
                        clipper: _TriangleClipper(position),
                        child: Container(
                          width: shapWidth,
                          height: shapHiehgt,
                          color: Colors.white,
                        ),
                      ),
                    )),
              ],
            ),
          ),
        ),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        key: _globalKey, onTap: () => _show(context), child: child);
  }
}

/// 画三角形
class _TriangleClipper extends CustomClipper<Path> {
  final LPopoverPosition position;
  _TriangleClipper(this.position);
  @override
  Path getClip(Size size) {
    Path path = Path();
    if (position == LPopoverPosition.top) {
      /// 尖朝下
      path.moveTo(0, 0);
      path.lineTo(size.width, 0);
      path.lineTo(size.width / 2, size.height);
    } else if (position == LPopoverPosition.bottom) {
      /// 尖朝上
      path.moveTo(0, size.height);
      path.lineTo(size.width / 2, 0);
      path.lineTo(size.width, size.height);
    }

    path.close();
    return path;
  }

  @override
  bool shouldReclip(CustomClipper oldClipper) {
    return oldClipper != this;
  }
}

/// 画三角形的边框
class _BorderPainter extends CustomPainter {
  final Color lineColor;
  final LPopoverPosition position;
  _BorderPainter({required this.lineColor, required this.position});
  @override
  void paint(Canvas canvas, Size size) {
    Paint p = Paint();
    p.color = lineColor;
    p.strokeWidth = lrpx(1);
    if (position == LPopoverPosition.top) {
      /// 尖朝下
      canvas.drawLine(
          const Offset(0, 0), Offset(size.width / 2, size.height), p);
      canvas.drawLine(
          Offset(size.width, 0), Offset(size.width / 2, size.height), p);
    } else if (position == LPopoverPosition.bottom) {
      /// 尖朝上
      canvas.drawLine(Offset(0, size.height), Offset(size.width / 2, 0), p);
      canvas.drawLine(
          Offset(size.width / 2, 0), Offset(size.width, size.height), p);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return oldDelegate != this;
  }
}
